#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <poll.h>
#include <unistd.h>

const static int MAX_CLIENTS = 10;

int main()
{
     // 1. 创建套接字
    int serverfd = socket(AF_INET, SOCK_STREAM, 0);
    if (serverfd < 0) {
        perror("socket failed");
        return -1;
    }

    // 2. 设置端口复用
    int opt = 1;
    int n = setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    if (n < 0) {
        perror("setsockopt failed");
        close(serverfd);
        return -2;
    }

    // 3. 绑定
    struct sockaddr_in addr;
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY; 
    addr.sin_port = htons(8080);

    n = bind(serverfd, (struct sockaddr*)&addr, sizeof(addr));
    if (n < 0) {
        perror("bind failed");
        close(serverfd);
        return -3;
    }

    // 4. 开始监听
    n = listen(serverfd, 8);
    if (n < 0) {
        perror("listen failed");
        close(serverfd);
        return -4;
    }

    // 5. 初始化 fds 数组
    struct pollfd fds[MAX_CLIENTS];
    fds[0].fd = serverfd;
    fds[0].events = POLLIN;

    int nfds = 1;

    char buffer[128] = {0};
    while (1) {
        // 6. 调用 poll 等待事件
        // int ready = poll(&fds, nfds, -1); // &fds 是数组指针
        int ready = poll(fds, nfds, -1); // fds（数组名）自动转换为 &fds[0]，指向数组的第一个元素
        if (ready < 0) {
            perror("poll failed");
            close(serverfd);
            return -5;
        }

        // 7. 检查套接字就绪
        for (int i = 0; i < nfds && ready > 0; i++) {

            if (fds[i].revents == 0) {
                continue;
            }

            ready--;

            // 8. 检查新连接
            if (fds[i].fd == serverfd && (fds[i].revents & POLLIN)) {
                struct sockaddr_in peer;
                bzero(&peer, sizeof(peer));
                socklen_t len = sizeof(peer);

                int clientfd = accept(serverfd, (struct sockaddr*)&peer, &len);
                if (clientfd < 0) {
                    perror("accept failed");
                    continue;
                }

                if (nfds >= MAX_CLIENTS) {
                    printf("Max clients reached. Rejected.\n");
                    close(clientfd);
                }
                else {
                    fds[nfds].fd = clientfd;
                    fds[nfds].events = POLLIN;
                    nfds++;
                }
            }
            else if (fds[i].revents & (POLLIN | POLLERR | POLLHUP)) {
                int clientfd = fds[i].fd;
                int cnt = recv(clientfd, buffer, 128, 0);
                buffer[cnt] = 0;
                
                if (cnt <= 0) {
                    close(clientfd);
                    continue;
                }
                else {
                    printf("clientfd: %d, count: %d, buffer: %s\n", clientfd, cnt, buffer);
                    send(clientfd, buffer, cnt, 0);
                }
            }
        }
    }

    close(serverfd);

    return 0;
}


// int main()
// {
//     // 1. 创建套接字
//     int serverfd = socket(AF_INET, SOCK_STREAM, 0);
//     if (serverfd < 0) {
//         perror("socket failed");
//         return -1;
//     }

//     // 2. 设置端口复用
//     int opt = 1;
//     int n = setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
//     if (n < 0) {
//         perror("setsockopt failed");
//         close(serverfd);
//         return -2;
//     }

//     // 3. 绑定
//     struct sockaddr_in addr;
//     bzero(&addr, sizeof(addr));
//     addr.sin_family = AF_INET;
//     addr.sin_addr.s_addr = INADDR_ANY; 
//     addr.sin_port = htons(8080);

//     n = bind(serverfd, (struct sockaddr*)&addr, sizeof(addr));
//     if (n < 0) {
//         perror("bind failed");
//         close(serverfd);
//         return -3;
//     }

//     // 4. 开始监听
//     n = listen(serverfd, 8);
//     if (n < 0) {
//         perror("listen failed");
//         close(serverfd);
//         return -4;
//     }

//     // 5. 初始化 pollfd 数组

//     /*
//     struct pollfd {
//         int fd;         // 文件描述符
//         short events;   // 关注的事件掩码
//         short revents;  // 实际发生的事件掩码
//     };
//     */

//     struct pollfd fds[MAX_CLIENTS];
//     int nfds = 1; // 当前数组中有效元素数量（初始只有监听套接字）

//     // 6. 设置监听套接字
//     fds[0].fd = serverfd;
//     fds[0].events = POLLIN;

//     char buffer[128] = {0};
//     while (1) {
//         // 7. 调用 poll 等待事件
//         int ready = poll(fds, nfds, -1); // 永久阻塞
//         if (ready < 0) {
//             perror("poll failed");
//             close(serverfd);
//             return -5;
//         }

//         // 8. 处理就绪事件
//         for (int i = 0; i < nfds && ready > 0; i++) {
//             // 跳过无事件 ID
//             if (fds[i].revents == 0) {
//                 continue;
//             }
            
//             // 优化：减少需检查的事件数
//             ready--;

//             // 9. 监听套接字就绪
//             // 使用 & 而不是 == 作为判断条件 -- 可能出现多个事件同时发生的情况
//             if (fds[i].fd == serverfd && (fds[i].events & POLLIN)) {
//                 struct sockaddr_in peer;
//                 bzero(&peer, sizeof(peer));
//                 socklen_t len = sizeof(peer);

//                 int clientfd = accept(serverfd, (struct sockaddr*)&peer, &len);
//                 if (clientfd < 0) {
//                     perror("accept failed");
//                     continue;
//                 }

//                 // 将新套接字加入 poll 数组
//                 if (nfds >= MAX_CLIENTS) {
//                     printf("Max clients reached. Rejected.\n");
//                     close(clientfd);
//                 }
//                 else {
//                     fds[nfds].fd = clientfd;
//                     fds[nfds].events = POLLIN; // 关注可读事件
//                     nfds++;
//                 }
//             }
//             else if (fds[i].revents & (POLLIN | POLLERR | POLLHUP)) {
//                 int sockfd = fds[i].fd;
                
//                 int cnt = recv(sockfd, buffer, 128, 0);
//                 if (cnt <= 0) {
//                     // 关闭文件描述符
//                     close(sockfd);
//                     // 从 poll 数组中移除
//                     fds[i] = fds[nfds - 1];
//                     nfds--;
//                 }
//                 else {
//                     printf("clientfd: %d, count: %d, buffer: %s\n", sockfd, cnt, buffer);
//                     send(sockfd, buffer, cnt, 0);
//                 }
//             }
//         }

//     }

//     close(serverfd);

//     return 0;
// }